
local ByteArray = require "quick.cc.utils.ByteArray"

local LoginView = import("..views.LoginView")
local LoginModel = import("..models.LoginModel")
local gameSeverNoticeModel = import("..models.gameSeverNoticeModel")

local LoginCodeView = import("..views.LoginCodeView")
local LoginNoticeView = import("..views.LoginNoticeView")
local LoginRoleView = import("..views.LoginRoleView")
local LoginCreateView = import("..views.LoginCreateView")

local LoginErrDialog = import("..views.LoginErrDialog")

local LoginController = class("LoginController",function()
    return display.newNode()
end)

local NumPerPage = 10
local gateHosts = nil

function LoginController:ctor(isEnterRolelist, battleGuideRoleId)
    self.token = nil
    self.gameAccount = nil
    self._isEnterRolelist = isEnterRolelist
    self._battleGuideRoleId = battleGuideRoleId

    gateHosts = app.channelAPI:getGateHostFromConfig()
    local model = LoginModel.new()
    local view = LoginView.new()

    -- 从新手战过来的
    if battleGuideRoleId then
        self:addLoginAniBg()

        self._musicId = AM.play("music/login.mp3", true, AM.TagMusic)
    end

    app.session:setHosts(gateHosts)

    model.hosts = gateHosts
    model.numPerPage = NumPerPage
    view.numPerPage = NumPerPage

    self.model = model
    self.view = view
    self:addChild(view)

    self.selectedZoneId = nil

    local appVersionStr = app:getFormatedVersionStr()
    --TODO
    local gameDBMD5 = ""
    view:setVersionCode(appVersionStr.." ("..gameDBMD5..")")

    view:onOperate(function(op, data)
        if op == "openZoneList" then
            self.view:setOpenListPlace(1)
            self:openZoneList(true)
        elseif op == "selectPage" then
            self:updateZoneList(data)
        elseif op == "selectZone" then
            self.selectedZoneId = data
            local zoneData = self.model:getZoneById(data)
            if zoneData then
                self.view:refreshZone(zoneData)
            end
        elseif op == "backFromZoneList" then
            -- 从服务器列表返回，灰度更新中不显示menu
            if not self._checkGrayZoneId then
                self.view:loginMenuVisibility(true)
            end
        elseif op == "enterGame" then
            local zoneId = self.selectedZoneId
            self:enterGame(zoneId)
        elseif op == "switchAccount" then
            self:switchAccount(true)
        elseif op == "openNotice" then
            if not self:displayLoginNotice() then
                display.pushToast(L("lua_code_text_103"))
            end
        elseif op == "openLink" then
            app.channelAPI:openURL(data)
        elseif op == "selectZoneByTag" then
            self.model:setSelectZoneListTag(data)
            self:openZoneList()
        end
    end)

    self:enableNodeEvents()

    if not self._isEnterRolelist then
        -- 非切换角色，拉取区服公告
        self:displayLoginNotice(true)
    end

    -- Tencent 腾讯灰度更新，一次运行一个区只检测一次
    local DisableHotfix = app.configuration:getValue("DisableHotfix")
    self._isNeedCheckGray = app:isTencent() and not DisableHotfix
    if self._isNeedCheckGray then
        self._grayZoneIdDict = {}
        app:addCustomEventListener("GRAY_UPDATE_COMPLETE", function(event)
            if self._grayCron then
                scheduler.cancelCron(self._grayCron)
                self._grayCron = nil
            end
            EM:notify("onDisplayIndicator", false)

            local userStr = event:getUserStr()
            if userStr == "comp" then
                -- 灰度更新结束
                self:hotFixLoadingVisibility(false)
                self:connectZone(self._checkGrayZoneId)
                self._grayZoneIdDict[self._checkGrayZoneId] = true
                self._checkGrayZoneId = nil
                self.view:loginMenuVisibility(true)
            elseif userStr == "update" then
                -- 灰度更新过程中
                self.view:loginMenuVisibility(false)
                self.view:serverListVisibility(false)
                self:hotFixLoadingVisibility(true)
            elseif userStr == "reload" then
                -- 需要重启游戏
                app:relaunchApp()
            end
        end, self)
    end

    -- 事件监听
    self._emHandle = EM:on("onChannelFriendsUpdate", handler(self, self.setCreateDefInfo))
    self._queueEnterHandle = EM:on("onEnterQueue", function()
        self:removeLoginErrDialog()
    end)
    self._queueCancelHandle = EM:on("onCancelQueue", handler(self, self.onCancelQueue))
    self._queueFailHandle = EM:on("onFailQueue", handler(self, self.onCancelQueue))
    self._logoutHandle = EM:on("OnGameLogout", function(eventName, ...)
        self:cleanFriendZoneList()
    end)
    
end

function LoginController:onExit()
    EM:remove(self._emHandle)
    EM:remove(self._queueEnterHandle)
    EM:remove(self._queueCancelHandle)
    EM:remove(self._queueFailHandle)
    EM:remove(self._connectZoneHandle)
    EM:remove(self._logoutHandle)

    self._emHandle = nil
    self._queueEnterHandle = nil
    self._queueCancelHandle = nil
    self._queueFailHandle = nil
    self._connectZoneHandle = nil
end

function LoginController:onEnterTransitionFinish()
    self:channelLogin()
end

function LoginController:addLoginAniBg()
    local node = cc.CSLoader:createNode(Res.LoginBgNode)
    node:setPosition(display.cx, display.cy)
    ccui.Helper:doLayout(node)
    local bg = node:getChildByName("bg")
    local scale = display.width / display.ui_width
    bg:setScale(scale)

    -- 底板骨骼特效
    local params = {
        armatureName = "login",
        path = "armatures/effect/login"
    }
    local Armature = app:getClass("Armature")
    local armBg = Armature.create(params)
    armBg:play("login", 0)
    node:getChildByName("Panel_ani"):addChild(armBg)

    self:addChild(node, -1)
end

function LoginController:displayErrorMsg(errorMsg,cb)
    local messageBox = display.newMessageBox(errorMsg,function()
        if cb then cb() end
    end)
    UIHandler:addPopDialog(messageBox)
end

-- loginType = 1 登陆大厅
-- loginType = 2 登录某服务器
function LoginController:openLoginErrDialog(errorMsg, okCB, cancelCB, loginType, confirmText)
    local loginErrDialog = self._loginErrDialog
    if not loginErrDialog then
        loginErrDialog = LoginErrDialog.new(errorMsg, okCB, cancelCB, loginType)
        loginErrDialog:setConfirmText(confirmText or L("CommonBtnRetry"))
        UIHandler:addPopDialog(loginErrDialog)
        self._loginErrDialog = loginErrDialog
    else
        loginErrDialog:setHint(errorMsg)
        if confirmText then
            loginErrDialog:setConfirmText(confirmText)
        end
    end
    local delayTime = loginErrDialog:refreshConfirmBtn()
    return delayTime
end

function LoginController:removeLoginErrDialog()
    if self._loginErrDialog then
        self._loginErrDialog:removeFromParent()
    end
    self._loginErrDialog = nil
end

-- 游戏公告（登录前）
function LoginController:displayLoginNotice(isNeedSendNotify)
    local noticeList = gameSeverNoticeModel:getLoginNoticeList()
    if #noticeList > 0 then
        if isNeedSendNotify then
            EM:notify("OnNoticePopUp")
        end

        self:_createNoticeView(noticeList)
        return true
    else
        return false
    end
end

function LoginController:_createNoticeView(noticeList, closeCB)
    local view = LoginNoticeView.new()
    view:setData( noticeList )
    view:setCloseDelegate(function()
        executeFunc(closeCB)
    end)
    view:setOpenUrlDelegate(function(url)
        app.channelAPI:openURL(url)
    end)
    UIHandler:addPopDialog(view)
end

function LoginController:isChannelLogined()
    local channelAPI = app.channelAPI
    return channelAPI:isLogin()
end

function LoginController:switchAccount(withConfirm)
    self._isEnterRolelist = false

    if withConfirm then
        local confirmDialog = display.newConfirmDialog(L("ConfirmSwitchAccount"),
            function()
                self.view:loginMenuVisibility(false)
                app.channelAPI:logout(function()
                    self:channelLogin()
                end)
               
            end)
        UIHandler:addPopDialog(confirmDialog)
    else
        self.view:loginMenuVisibility(false)
        app.channelAPI:logout(function()
            self:channelLogin()
        end)
        
    end
end

function LoginController:channelLogin()
    -- app.channelAPI:setLogoutCallback(function()  app:relaunchApp() end)
    if app.channelAPI:isLogin() then
        self:fetchServerList()
    else
        local cb=function(api,ret,err)
            if ret == "success" then
                EM:notify("OnChannelLogined")
                self:fetchServerList()
            elseif ret =="fail" then
                local msg = err or L("tips_3000125")
                print("channel.login error", msg)
            end
        end
        EM:notify("OnShowSdkLogin")
        app.channelAPI:login(cb)
    end
end

function LoginController:fetchServerList(newHost)
    local curTime = math.floor(app:getTime())
    local lastTime = app:getValue(Enums.UserDefaultKey.LoginFailTime, 0)
    if (curTime - lastTime) < Constant.LOGIN_DISABLE_MAX_TIME then
        self:openLoginErrDialog(L("network_error"),function()
                self:fetchServerList()
                self.view:loginMenuVisibility(false)
            end, nil, 1)
    else
        app.channelAPI:fetchServerList(handler(self,LoginController.onFetchServerList), newHost)
    end

end

function LoginController:isGameLogined()
    return app.session:isLogined()
end

function LoginController:onFetchServerList(...)
    if app:getPublisher() == Enums.Publisher.ema then
        self:onEmaOverseaFetchServerListFinished(...)
    else
        self:onNormalGameLoginFinished(...)
    end
end

function LoginController:onGameLoginFinished(...)
    if app:getPublisher() == Enums.Publisher.ema then
        self:onEmaOverseaGameLoginFinished(...)
    else
        self:onNormalGameLoginFinished(...)
    end
end

function LoginController:onEmaOverseaFetchServerListFinished(visited_servers, recommend_server)
    local model = self.model
    model:clear()
    model:parseRecommendZone(recommend_server)
    model:parseVisitedZone(visited_servers, true)

    self.view:loginMenuVisibility(true)

    EM:notify("OnOverseaFetchServerSuccess")

    local view = self.view
    local lastLoginZone= model:getLastLoginZone()
    if lastLoginZone then
        self.selectedZoneId = tonumber(lastLoginZone.id)
        view:refreshZone(lastLoginZone)
    end

    if self._isEnterRolelist then
        self:enterGame(self.selectedZoneId)
    end
end

function LoginController:onEmaOverseaGameLoginFinished(decode,errorMsg,code, zoneId)
-- 网络错误
    if errorMsg then
        self:displayErrorMsg(errorMsg,function()
                self:fetchServerList()
                self.view:loginMenuVisibility(false)
            end)

            GemService:SetEvent(5, false, tostring(code), false, false)
        return
    end

    local data = decode.data
    local msg = decode.msg
    local ret = decode.ret
    -- 逻辑错误
    if ret > 0 then
        -- 激活码界面
        if msg == "ErrActivateError" then self:openCodeView() return end

        self:displayErrorMsg(L(msg),function()
            if msg == "ErrAccountBan" or
                msg == "ErrMaintainServer" or
                msg == "ErrTestingGame" or
                msg == "ErrVerifyError" then
                -- 封号／不在白名单／不在内网白名单（自己测试用）／验证失败 重新登陆
                self:switchAccount()
            else
                self:fetchServerList()
                self.view:loginMenuVisibility(false)

                GemService:SetEvent(5, false, tostring(code), false, false)
            end
        end)
        return 
    end

    self:removeLoginErrDialog()
    
    -- 请求成功，显示服务端返回的内容
    local token = data.token
    -- print("---------token",token)
    local gameAccount = data.game_account

    local model = self.model
    model.account = gameAccount
    model.token = token

    self.token = token
    self.gameAccount = gameAccount

    EM:notify("OnGameLogined",{account=self.gameAccount})

    if zoneId then
        self:connectZone(zoneId)
        -- self:enterGame(self.selectedZoneId)
    end
end

-- ema
function LoginController:onNormalGameLoginFinished(decode,errorMsg,code)    
    -- 网络错误
    print("====================>> onNormalGameLoginFinished")
    if errorMsg then
        self:openLoginErrDialog(errorMsg, function()
                self:fetchServerList()
                self.view:loginMenuVisibility(false)
            end, nil, 1)

        GemService:SetEvent(5, false, tostring(code), false, false)
        return
    end

    local data = decode.data
    local msg = decode.msg
    local ret = decode.ret
    -- 逻辑错误
    if ret > 0 then
        -- 激活码界面
        if msg == "ErrActivateError" then self:openCodeView() return end

        local confirmText
        if msg == "ErrAccountBan" or
            msg == "ErrMaintainServer" or
            msg == "ErrTestingGame" or
            msg == "ErrVerifyError" then
            confirmText = L("CommonBtnConfirm")
        end
        self:openLoginErrDialog(GD:getMessageStr(msg),function()
            if msg == "ErrAccountBan" or
                msg == "ErrMaintainServer" or
                msg == "ErrTestingGame" or
                msg == "ErrVerifyError" then
                -- 封号／不在白名单／不在内网白名单（自己测试用）／验证失败 重新登陆
                self:removeLoginErrDialog()
                self:switchAccount()
            else
                self:fetchServerList()
                self.view:loginMenuVisibility(false)

                GemService:SetEvent(5, false, tostring(code), false, false)
            end
        end, nil, 1, confirmText)
        return 
    end

    self:removeLoginErrDialog()

    -- -- iOS提审包重定向到提审服
    -- if data.redirecturl and data.redirecturl ~= "" then
    --     app.session:clearLogined()
    --     self:fetchServerList(data.redirecturl)
    --     self.view:loginMenuVisibility(false)
    --     app.channelAPI:setIsReivew(true)
    --     return
    -- end

    --弹出 首次实名弹窗
    if app.channelAPI:checkIsNeedPopFirstRealName() then
        local msg = L("您的实名信息已存在于腾讯平台的账号实名库，目前可以正常登陆腾讯游戏进行体验，请确定") --@ignore
        self:displayErrorMsg(msg, function()
            app.channelAPI:setFirstRealNamePopUp()
        end)
    end


    -- gsdk 埋点
    GemService:SetEvent(5, true, "success", false, false)

    self.view:loginMenuVisibility(true)

    -- 请求成功，显示服务端返回的内容
    local total = tonumber(data.total)
    local token = data.token

    -- print("---------token",token)

    local gameAccount = data.game_account

    local model = self.model
    model:clear()
    model:parseRecommendZone(data.recommend_server)
    model:parseVisitedZone(data.visited_servers)

    -- 登录成功去拉取好友服务器（有缓存）
    model:getMsdkAllFriendZoneList()

    model.zoneCount = total
    model.account = gameAccount
    model.token = token
    self.token = token
    self.gameAccount = gameAccount

    local view = self.view

    local lastLoginZone= model:getLastLoginZone()
    if lastLoginZone then
        self.selectedZoneId = tonumber(lastLoginZone.id)
        view:refreshZone(lastLoginZone)
    end

    EM:notify("OnGameLogined",{account=self.gameAccount})
    if self._isEnterRolelist then
        self:enterGame(self.selectedZoneId)
    end
end


function LoginController:openCodeView()
    local view = LoginCodeView.new()
    view:onOperate(function(op, code)
        if op == "closeView" then
            view:removeFromParent()
            self:switchAccount()
        elseif op == "getCode" then
            local msg = L("测试期间将在极光平台发放激活码，点击前往下载极光APP。") --@ignore
            local confirmDialog = app.mvc.DialogBase.new(msg,
                function()
                    local codeUrl = app:getLoginCodeUrl()
                    app.channelAPI:openURL(codeUrl)
                end,
                function()
                    
                end)
            confirmDialog:setConfirmText(L("lua_code_text_135"))
            self:addChild(confirmDialog)
        elseif op == "useCode" then
            local ary = {gateHosts, "activate?", "code=", code, 
                "&channel=", app.channelAPI:getChannelId(), 
                "&channelUID=", app.channelAPI:getOpenId()}
            local url = table.concat(ary)
            app.session:useCode(url, nil, function(decode,errorMsg,code)
                    if errorMsg then
                        self:displayErrorMsg(L(errorMsg),function()
                            self:fetchServerList()
                            self.view:loginMenuVisibility(false)
                        end)
                        GemService:SetEvent(5, false, tostring(code), false, false)
                    else
                        local isAvtivated = true
                        if decode.ret > 0 then
                            -- already_activated 已经激活
                            -- activate_code_not_exists 激活码不存在
                            -- activate_code_used 激活码已使用
                            local msg = decode.msg
                            display.pushToast(L(msg))
                            isAvtivated = (msg == "already_activated")
                        end
                        if isAvtivated then
                            self:fetchServerList()
                            self.view:loginMenuVisibility(false)
                            view:removeFromParent()
                        else
                            view:clearText()
                        end
                    end
                end)
        end
    end)
    self:addChild(view)
    view:show()
end

function LoginController:openZoneList(forceRequest)
    if cc.isDead(self.view) then return end

    -- local total = self.model.zoneCount
    -- if total == -1 then
    --     --ema 海外  
    --     -- total = 0
    --     -- pageCount = 0
    --     -- 拉取 服务器列表
    --     model:fetchRange(1,function(model,errorMsg, zoneCount)
    --         if cc.isDead(self) then return end
    --         self.model.zoneCount = zoneCount or 0
    --         self:openZoneList()
    --     end)
    --     return
    -- end

    if forceRequest then
        -- 强制拉取新信息
        self.model:fetchRange(1, function()
            self:openZoneList()
        end)
        return
    end

    local model = self.model
    local total = model.zoneCount
    local pageCount = model:getPageCount(total)
    local friendZones = self:getMsdkAllFriendZoneList() or {}
    self.view:openZoneList()
    self.view:buildPageList(pageCount,total,model:hasVisitedZone(), #friendZones > 0, model:hasRecommendZone())
end

function LoginController:updateZoneList(pageNum)
    local model = self.model
    local view = self.view
    if pageNum==0 then
        local visitedZoneList = model.visitedZoneList
        view:updateZoneList(visitedZoneList)
    elseif pageNum == 999999 then
        local friends = self:getMsdkAllFriendZoneList() or {}
        if #friends > 0 then
            view:updateZoneList({isFriend = true, data = friends})
        else
            view:updateZoneList({})
        end
    elseif pageNum == 999998 then
        view:updateZoneList(model:getRecommendZoneList())
    else
        -- local zoneList = model:getZoneListByPage(pageNum)
        -- if #zoneList == 0 then
        --     model:fetchRange(pageNum,function(model,errorMsg)
        --         if errorMsg then
        --             self:displayErrorMsg(errorMsg)
        --             return 
        --         end
        --         local zoneList = model:getZoneListByPage(pageNum)
        --         view:updateZoneList(zoneList)
        --     end)
        -- else
        --     view:updateZoneList(zoneList)
        -- end
        local zoneList = model:getZoneListByPage(pageNum)
        view:updateZoneList(zoneList)
    end

end

function LoginController:enterGame(zoneId)
    if not self:isChannelLogined() then
        self:channelLogin()
        --print("====>enterGame fail channel didn't login")
        return 
    end
    if not zoneId then
        release_print("zoneId is nil")
        return
    end
    if not self:isGameLogined() then
        local model = self.model
        local zoneData = assert(model:getZoneById(zoneId))
        app.channelAPI:gameLogin(function(decode,errorMsg,code)
            self:onGameLoginFinished(decode,errorMsg,code, zoneId)
        end, zoneData)
        --print("====>enterGame fail didn't login")
        return 
    end

    -- 检测服务器数据和状态
    if not zoneId then
        release_print("enterGame zoneId is nil")
        return
    end

    local model = self.model
    local zoneData = model:getZoneById(zoneId)
    if not zoneData then
        release_print("=====>> enterGame zoneData is nil")
        return
    end

    -- if zoneData.status == "4" then
    --     self:displayErrorMsg(L("ErrServerMaintain"))
    --     return
    -- end

    -- 考虑合服，区服公告以及灰度更新使用合服id
    local realZoneId = zoneId
    if zoneData.mergeId and zoneData.mergeId > 0 then
        realZoneId = zoneData.mergeId
    end

    local function tryConnectZone()
        if not self._isEnterRolelist and self._isNeedCheckGray and not self._grayZoneIdDict[realZoneId] then
            -- 开始灰度更新，若无更新很快会有返回，5s还无返回应该是出了啥问题，主动关闭转菊花，切到热更
            self._grayCron = scheduler.newCron(function()
                self._grayCron = nil
                self.view:loginMenuVisibility(false)
                self.view:serverListVisibility(false)
                self:hotFixLoadingVisibility(true)
                EM:notify("onDisplayIndicator", false)
            end, 5)

            self._checkGrayZoneId = realZoneId
            local openId = app.channelAPI:getOpenId()
            EM:notify("onDisplayIndicator", true)
            cc.startGrayUpdate(openId, realZoneId .. "")
        else
            self:connectZone(zoneId)
        end
    end

    -- 非切换角色，先检测是否有公告
    if not self._isEnterRolelist then
        local noticeList = gameSeverNoticeModel:getLoginZoneNoticeById(realZoneId)
        if noticeList and #noticeList > 0 then
            self:_createNoticeView(noticeList, tryConnectZone)
            return
        end
    end

    tryConnectZone()
end

function LoginController:_onZoneConnected(zoneId)
    local zoneData = self.model:getZoneById(zoneId)
    if zoneData.roleNum > 0 then
        self._zoneData = zoneData
        self._roles = self.model:getRolesByZoneId(zoneId)
        self:openRoleView(zoneData, self._roles)
    else
        self:openCreateView(1)
    end
end

function LoginController:openConnnectFailDialog(zoneId, errorMsg)
    self:openLoginErrDialog(errorMsg, function()
            self:connectZone(zoneId)
        end, function()
            self._loginErrDialog = nil
        end, 2)
end

function LoginController:connectZone(zoneId)
    if not zoneId then
        release_print("connectZone zoneId is nil")
        return
    end

    local model = self.model
    local zoneData = model:getZoneById(zoneId)
    if not zoneData then
        release_print("=====>> connectZone zoneData is nil")
        return
    end

    --local roles = zoneData.roles
    app.session:setWsUrl(zoneData.addr)
    app.session:setZoneId(zoneId, zoneData.mergeId)
    app.session:setZoneName(zoneData.name)

    -- 考虑合服，检测间隔以及gsdk上报使用合服id
    local realZoneId = zoneId
    if zoneData.mergeId and zoneData.mergeId > 0 then
        realZoneId = zoneData.mergeId
    end

    -- 检测是否过了连接间隔
    local curTime = math.floor(app:getTime())
    local key = Enums.UserDefaultKey.LoginFailTime .. "_" .. realZoneId
    local lastTime = app:getValue(key, 0)
    if (curTime - lastTime) < Constant.LOGIN_DISABLE_MAX_TIME then
        self:openConnnectFailDialog(zoneId, L("tips_1000094"))
        return
    end

    -- 点击进入游戏按钮
    GemService:SetEvent(6, true, tostring(realZoneId), false, false)

    self._isEnterRolelist = false
    
    -- connect zone
    -- 断开连接成功之后再行连接，否则回调会有错乱
    app.session:disconnect(function()
        app.session:connect(function(errorMsg, code, msg)
            if errorMsg then
                self:openConnnectFailDialog(zoneId, errorMsg)
            else
                self:removeLoginErrDialog()
                model:setZoneRoles(zoneId, msg)
                self:_onZoneConnected(zoneId)
            end
        end)
    end)
end

function LoginController:createRole(createRoleInfo)
    self.model:createRole(createRoleInfo, function(msg)
        local zoneData = self.model:getZoneById(self.selectedZoneId)
        EM:notify("OnRoleCreated", msg.uid, zoneData)
        self:connectGame(msg.uid)
    end)
end

function LoginController:connectGame(uid)
    app.session:enterGame(uid, function(isFail)
        if isFail then -- 角色登录失败（断网）
            EM:notify("onRoleLoginFailed")
        else
            self:_onGameConnected(uid)
        end
    end)
end

function LoginController:_onGameConnected(uid)
    print("====================>> _onGameConnected")
    GemService:SetEvent(7, true, "success", false, true)

    local oldZoneId = app.session:getOldZoneId()
    local realZoneId = app.session:getZoneId()
    local zoneData = self.model:getZoneById(oldZoneId)

    UD:initZoneData(uid, realZoneId, zoneData.name, zoneData.utc)
    
    --Bugly API not Thread Safe
    app.crashReportAPI.setUserId(table.concat({uid,realZoneId},"_"))

    app.channelAPI:setRecivePushCallback(function(payload)
        -- print("OnRecivice PushNotification ",payload)
        EM:notify("OnRevicePushNotification",{payload=payload})
    end)

    -- 设置TApm的userId
    local platform = app.channelAPI:getWGPlatform()
    local openid = app.channelAPI:getOpenId()
    tapm.setUserId(openid)

    --获取安全SDK的核心初始化数据，并放到游戏的初始化协议Buffer中，托传到服务端。
    if safeapi and app:getPublisher() == Enums.Publisher.tencent then
        local data = safeapi.getCoreData()
        -- local bytes = ByteArray.new()
        -- bytes:writeString(data)
        -- print("SafeSDK.getCoreData toString", bytes:toString())

        app.session:request("tencent.C2S_SafeReport", {type=0, content=data})
        
        safeapi.onLogin(platform, openid, realZoneId, uid.."")
        safeapi.isLogin = true       
    end
    -- gsdk 设置name
    GemService:SetUserName(platform, openid)

    app.channelAPI:setPushTag("zone_" .. realZoneId)
    app.crashReportAPI.addUserValue("nickname",UD:getNickName() or "none")
    app.crashReportAPI.addUserValue("resversion",app:getResVersion() or "none")
    app.crashReportAPI.addUserValue("zonename",app.session.zoneName or "none")
   
    app.channelAPI:reportConnectServer()

    self:loginCompleted()
end

function LoginController:hotFixSceneVisibility(visible)
    EM:notify("OnHotFixSceneVisibility",{visible = visible})
end

function LoginController:hotFixLoadingVisibility(visible)
    EM:notify("OnHotFixLoadingVisibility",{visible = visible})
end

function LoginController:_closeCreateView()
    if self._createView then
        self._createView:removeFromParent()
        self._createView = nil
    end
end

function LoginController:setCreateDefInfo()
    if self._createView then
        local myInfo = app.channelAPI:queryMyInfo()
        self._createView:setUserInfo(myInfo)
    end
    if self.view and self.view:isZoneViewVisible() then
        -- 好友信息刷新的时候 请求msdk 区服信息 避免 好友信息没拉完  就请求qq微信同玩好友
        self:getMsdkAllFriendZoneList()
    end

end

-- 对随机名字也进行脏字检测，直到检测合格为止
function LoginController:_getRandomName()
    if cc.isDead(self._createView) then return end

    local name = GD:randomNickName(Constant.NICKNAME_MAX_LEN)
    print("LoginController:_getRandomName", name)
    if app:isNeedCheckInput() then
        app:checkInput(name, function(response,errorMsg,code)
            if code == 200 then
                if response and response.result then
                    if not cc.isDead(self._createView) then
                        self._createView:setName(name)
                    end
                else
                    self:_getRandomName()
                end
            else
                display.pushToast(L("network_error"))
            end
        end, false, true)
    else
        self._createView:setName(name)
    end
end

function LoginController:openCreateView(place)
    self.view:loginMenuVisibility(false)
    self.view:serverListVisibility(false)
    self:hotFixSceneVisibility(false)

    local view = LoginCreateView.new(app.mvc.VIEWTYPE_FULL)
    self._createView = view
    self:addChild(view)
    EM:notify("OnEnterRoleCreatedView")
    view:onOperate(function(op, data)
        if op == "exit" then
            self:_closeCreateView()
            if place == 1 then
                self.view:loginMenuVisibility(true)
                self:hotFixSceneVisibility(true)
                self:hotFixLoadingVisibility(false)
            elseif place == 2 then
                self:openRoleView(self._zoneData,self._roles)
            end
        elseif op == "randomName" then
            self:_getRandomName()
        elseif op == "enter" then
            -- dump(data, "Login Create params")
            if app:isNeedCheckInput() then
                app:checkInput(data.name, function(response,errorMsg,code)
                    if code == 200 then
                        if response and response.result and not cc.isDead(self) then
                            self:createRole(data)
                        else
                            display.pushToast(L("lua_code_text_11"))
                        end
                    else
                        display.pushToast(L("network_error"))
                    end
                end)
            else
                self:createRole(data)
            end
        end
    end)

    self:setCreateDefInfo()
    self._createView:refresh(GD:getCreateDatas(), self._battleGuideRoleId)
end

function LoginController:_closeRoleView()
    if self._roleView then
        self._roleView:removeFromParent()
        self._roleView = nil
    end
end

function LoginController:onCancelQueue()
    self:hideRoleView()
    self.view:setOpenListPlace(1)
    self:openZoneList(true)
end

function LoginController:hideRoleView()
    if self._roleView then
        self._roleView:setVisible(false)
    end
end

function LoginController:openRoleView(zoneData, roles)
    self:loginViewVisibility(false)

    zoneData = zoneData or self.model:getZoneById(self.selectedZoneId)
    local lastLoginRole = self.model:getLastLoginRole(zoneData.id)

    if not self._roleView then
        self._roleView = LoginRoleView.new(app.mvc.VIEWTYPE_FULL)
        self:addChild(self._roleView)
        self._roleView:onOperate(function(op, data)
            if op == "exit" then
                self:_closeRoleView()
                self:loginViewVisibility(true)
                self.view:serverListVisibility(false)
                self.view:loginMenuVisibility(true)
                self:hotFixSceneVisibility(true)
                self:hotFixLoadingVisibility(false)
            elseif op == "enter" then
                self:connectGame(data.uid)
            elseif op == "server" then
                self:hideRoleView()
                self:loginViewVisibility(true)
                self.view:setOpenListPlace(2)
                self:openZoneList(true)
            elseif op == "create" then
                self:hideRoleView()
                self:loginViewVisibility(true)
                self:openCreateView(2)
            elseif op == "delete" then
                local uid = data.uid
                local confirmDialog = display.newConfirmDialog(L("lua_code_text_112"),
                    function() 
                        local curSelectZoneData = self.model:getZoneById(self.selectedZoneId)
                        if curSelectZoneData then
                            self.model:deleteRole(curSelectZoneData.id, uid, function(msg)
                                if msg.ok then
                                    local roles = self.model:getRolesByZoneId(curSelectZoneData.id)
                                    if #roles > 0 then
                                        local lastRole = self.model:getLastLoginRole(curSelectZoneData.id)
                                        self._roleView:refreshList(roles, lastRole)
                                    else
                                        self:_closeRoleView()
                                        self:loginViewVisibility(true)
                                        self:openCreateView(1)
                                    end
                                end
                            end)
                        end
                        
                    end)
                UIHandler:addPopDialog(confirmDialog)
            end
        end)
    end

    self._roleView:setVisible(true)
    self._roleView:refreshList(roles, lastLoginRole)
    self._roleView:refreshZone(zoneData)
end

function LoginController:loginViewVisibility(visible)
    self.view:setVisible(visible)
end

function LoginController:loginCompleted()
    print("====================>> loginCompleted")
    AM.stopAll()
    if cc.isAlive(self) then
        self:removeFromParent(true)
    end
    EM:notify("OnGameConnected")
end

function LoginController:getMsdkAllFriendZoneList()
    if self.model then
        return self.model:getMsdkAllFriendZoneList(handler(self, self.openZoneList))
    end
    return {}
end

function LoginController:cleanFriendZoneList()
    if self.model then
        self.model:cleanFriendZoneList()
    end
end

    
return LoginController
